
//Canvas像素坐标比例
let canvasXRate = canvas.width / mcanvas.getBoundingClientRect().width;
let canvasYRate = canvas.height / mcanvas.getBoundingClientRect().height;
$(window).resize(function () {
	// // console.log('resize');
	canvasYRate = canvas.height / mcanvas.getBoundingClientRect().height;
	canvasXRate = canvas.width / mcanvas.getBoundingClientRect().width;
});

//图形绘制状态信息
const shapeState = {
	started: false,
	startPoint: null,
	endPoint: null,
	shape: null
};

//橡皮擦状态信息
const eraserState = {
	started: false,
	target: null
};

//文字工具状态信息
const textState = {
	isEditing: false,
	target: null //正编辑的对象
};

const brushState = {
	started: false,
	color: palette.css('color')
};
//可以填充的形状类型
const fillableType = ['rect', 'circle', 'triangle', 'ellipse', 'polygon'];

//字号和canvas内画笔粗细对应
const textSizeMap = {
	word: ['小五', '五号', '小四', '四号', '小三', '三号',
		'小二', '二号', '小一', '一号', '小初', '初号'],
	px: [12, 14, 16, 18.67, 20, 21.3, 24, 29.3, 32, 34.67, 48, 56]
};
textSizeMap.px.forEach(function (val, idx) {
	textSizeMap.px[idx] = val * canvasXRate;
});

//初始化选中第一项工具
$('#selector').parent().click();
$('input[name="pen-size"]:first').parent().click();
$('#shape-line').parent().click();

//初始化绘图属性
canvas.freeDrawingBrush.width = Math.round(canvasYRate * parseFloat($('input[name="pen-size"]:checked').next().css('height')));
canvas.freeDrawingBrush.color = palette.css('color');
//初始设置为四号
const textSize = $('#text-size-value');
textSize.text(textSizeMap.word[3]);

//绘图工具切换
$('input[name="tools"]').change(function () {
	const tool = this.id;
	canvas.getObjects('i-text').forEach(function (o) {
		o.exitEditing();
		// if(tool === 'text'){
			// o.set('editable',true);
			// o.set('hasControls', true);
		// }else{
			// o.set('editable',false);
		// }
	});
	if (tool === 'selector') {
		canvas.forEachObject(function (o) {
			o.selectable = true;
		});
		canvas.selection = true;
	} else {
		canvas.forEachObject(function (o) {
			o.selectable = false;
		});
		canvas.selection = false;
	}
	canvas.isDrawingMode = (tool === 'pencil');
	canvas.perPixelTargetFind = (tool === 'eraser' || tool === 'brush');

	if (tool === 'image') {
		selectImage();
		$('#selector').parent().click();
	}
	canvas.discardActiveObject();
	canvas.renderAll();
});


$('input[name="pen-size"]').change(function () {
	canvas.freeDrawingBrush.width = Math.round(canvasYRate * $(this).next().css('height').slice(0, -2));
	// console.log(canvas.freeDrawingBrush.width);
});


//调色板
ColorPicker(
	document.getElementById('slide'),
	document.getElementById('picker'),
	function (hex, hsv, rgb) {
		palette.css('color', hex);
		canvas.freeDrawingBrush.color = hex;
	}
);

//填充色调色板
ColorPicker(
	document.getElementById('fill-slide'),
	document.getElementById('fill-picker'),
	function (hex, hsv, rgb) {
		$('#shape-fill-color').css('background', hex);
		$('#shape-fill-palette').animate({height:'0px'},'fast',function(){
			$(this).hide();
		});
	}
);

$('#tool-shape-icon').click(function(){
	$('#shape-fill-palette').animate({height:'0px'},'fast',function(){
		$(this).hide();
	});
});

$('#shape-fill-label').click(function(){
	const div = document.getElementById('shape-fill-palette');
	if(div.style.height === '16.1rem'){
		$(div).animate({height:'0px'},'fast',function(){
			$(div).hide();
		});
	}else{
		$(div).show();
		$(div).animate({height:'16.1rem'},'fast');
	}
});

$('#fill-transparent').click(function(){
	$('#shape-fill-color').css('background', 'url(icon/transparent.jpg) no-repeat').css('background-size','cover');
	$('#shape-fill-palette').animate({height:'0px'},'fast',function(){
		$(this).hide();
	});
});

$('#fill-black').click(function(){
    $('#shape-fill-color').css('background', 'black');
    $('#shape-fill-palette').animate({height:'0px'},'fast',function(){
        $(this).hide();
    });
});
$('#fill-white').click(function(){
    $('#shape-fill-color').css('background', 'white');
    $('#shape-fill-palette').animate({height:'0px'},'fast',function(){
        $(this).hide();
    });
});


$('#incTextSize').click(function () {
	const index = textSizeMap.word.indexOf(textSize.text());
	const value = textSizeMap.word[index + 1];
	if (value) {
		textSize.text(value);
	}
});
$('#decTextSize').click(function () {
	const index = textSizeMap.word.indexOf(textSize.text());
	const value = textSizeMap.word[index - 1];
	if (value) {
		textSize.text(value);
	}
});

canvas.on('mouse:down', function (options) {
    // console.log('down');
    // console.log(options.e);
    if(options.e.touches){
        options.e.offsetX = options.e.touches[0].pageX - $(mcanvas).offset().left;
        options.e.offsetY = options.e.touches[0].pageY - $(mcanvas).offset().top;
    }
    const point = {
        x: options.e.offsetX * canvasXRate,
        y: options.e.offsetY * canvasYRate
    };
    effect.moveTo(canvas.size()-1);
    switch ($('input[name="tools"]:checked').attr('id')) {
        case 'shape':
            if(!$('#shape-fill').prop('checked')){
                shapeState.started = true;
                shapeState.startPoint = point;
                shapeState.shape = createShape(point);
                canvas.add(shapeState.shape);
            }else{
                fillShape(options.target);
            }
            break;
        case 'eraser':
            effect.set('fill','rgba(100,100,100,0.5)');
            eraserState.started = true;
            eraseTarget(point, options.target);
            break;
        case 'text':
            handleText(point, options.target);
            break;
        case 'brush':
            brushState.color = palette.css('color');
            brushState.started = true;
            strokeTarget(point, options.target);
            break;
        default:
            break;
    }
});

$(mcanvas.nextSibling).mouseout(function(){
	switch ($('input[name="tools"]:checked').attr('id')) {
		case 'eraser':
			eraserState.started = false;
			effect.set('left', canvas.width);
			break;
		case 'shape':
			finishShape(shapeState);
			showFillTarget(null);
			break;
		case 'brush':
			brushState.started = false;
			effect.set('left', canvas.width);
			break;
		default:
			break;
	}
	canvas.renderAll();
});

canvas.on('mouse:move', function (options) {
    // console.log('move');
    // console.log(options.e);
    if(options.e.touches){
        options.e.offsetX = options.e.touches[0].pageX - $(mcanvas).offset().left;
        options.e.offsetY = options.e.touches[0].pageY - $(mcanvas).offset().top;
    }
    const point = {
        x: options.e.offsetX * canvasXRate,
        y: options.e.offsetY * canvasYRate
    };

    switch ($('input[name="tools"]:checked').attr('id')) {
        case 'shape':

            if(!$('#shape-fill').prop('checked')){
                //绘制形状
                canvas.setCursor('crosshair');
                if(shapeState.started){
                    shapeState.endPoint = point;
                    drawShape(shapeState);
                }
            }else{
                //填充形状
                canvas.setCursor('url(icon/paint_bucket.ico),pointer');
                showFillTarget(options.target);
                canvas.renderAll();
            }
            break;
        case 'eraser':
            eraseTarget(point, options.target);
            break;
        case 'text':
            setTextCursor(options.target);
            break;
        case 'brush':
            strokeTarget(point, options.target);
            break;
        default:
            break;
    }
});

canvas.on('mouse:up', function (options) {
	switch ($('input[name="tools"]:checked').attr('id')) {
		case 'shape':
			if(!$('#shape-fill').prop('checked')){
				canvas.setCursor('crosshair');
				finishShape(shapeState);
			}else{
				canvas.setCursor('url(icon/paint_bucket.ico),pointer');
			}
			break;
		case 'eraser':
			eraserState.started = false;
			effect.set('left', canvas.width);
			break;
		case 'pencil':
			if(options.target && options.target.type === 'path'){
				options.target.perPixelTargetFind = true;
			}
			break;
		case 'brush':
			//canvas.setCursor('url(icon/brush.ico),pointer');
			canvas.setCursor('pointer');
			brushState.started = false;
			effect.set('left', canvas.width);
			break;
		default:
			break;
	}
    DocManager.currentDoc.getPage(parseInt(currentPageNumber.text())).save(getCanvasJson());
});

const lineWidth = 3;
function createShape(startPoint) {
	const color = $('#shape-fill-color').css('background-color');
	switch ($('input[name="choose-shape"]:checked').attr('id')) {
		case 'shape-line':
			return new fabric.Line([startPoint.x, startPoint.y, startPoint.x, startPoint.y], {
				stroke: palette.css('color'),
				strokeWidth: lineWidth,
				width: 0,
				height: 0,
				perPixelTargetFind: true
			});
		case 'shape-rect':
			return new fabric.Rect({
				stroke: palette.css('color'),
				strokeWidth: lineWidth,
				width: 0,
				height: 0,
				fill: color
			});
		case 'shape-circle':
			return new fabric.Circle({
				stroke: palette.css('color'),
				strokeWidth: lineWidth,
				width: 0,
				height: 0,
				fill: color
			});
		case 'shape-triangle':
			return new fabric.Triangle({
				stroke: palette.css('color'),
				strokeWidth: lineWidth,
				width: 0,
				height: 0,
				fill: color
			});
		case 'shape-ellipse':
			return new fabric.Ellipse({
				stroke: palette.css('color'),
				strokeWidth: lineWidth,
				width: 0,
				height: 0,
				fill: color
			});
		case 'shape-star':
            return new fabric.Polygon([]);
        case 'shape-arrow':
            return new fabric.Polyline([]);
		default:
			return null;
	}
}

function drawShape(shapeState) {
	if (!shapeState.started)
		return;
    // console.log('draw shape');
	const color = $('#shape-fill-color').css('background-color');
	const startPoint = shapeState.startPoint;
	const endPoint = shapeState.endPoint;
    const width = endPoint.x - startPoint.x;
    const height = endPoint.y - startPoint.y;
    const min = Math.min(Math.abs(width), Math.abs(height));
	switch ($('input[name="choose-shape"]:checked').attr('id')) {
		case 'shape-line':
			shapeState.shape.set({
				x2: endPoint.x,
				y2: endPoint.y
			});
			break;
		case 'shape-rect':
		case 'shape-triangle':
			shapeState.shape.set({
				left: Math.min(endPoint.x, startPoint.x),
				top: Math.min(endPoint.y, startPoint.y),
				width: Math.abs(endPoint.x - startPoint.x),
				height: Math.abs(endPoint.y - startPoint.y)
			});
			break;
		case 'shape-circle':
			shapeState.shape.set({
				left: width<0 ? startPoint.x - min : startPoint.x,
				top: height<0 ? startPoint.y - min : startPoint.y,
				radius: Math.min(Math.abs(endPoint.x - startPoint.x), Math.abs(endPoint.y - startPoint.y)) / 2,
			});
			break;
		case 'shape-ellipse':
			shapeState.shape.set({
				left: Math.min(endPoint.x, startPoint.x),
				top: Math.min(endPoint.y, startPoint.y),
				rx: Math.abs(endPoint.x - startPoint.x) / 2,
				ry: Math.abs(endPoint.y - startPoint.y) / 2
			});
			break;
		case 'shape-star':
			canvas.remove(shapeState.shape);
			const radius = Math.min(Math.abs(endPoint.x - startPoint.x), Math.abs(endPoint.y - startPoint.y)) / 2;
			shapeState.shape = new fabric.Polygon(starPolygonPoints(radius, radius / 2), {
                left: width<0 ? startPoint.x - min : startPoint.x,
                top: height<0 ? startPoint.y - min : startPoint.y,
				stroke: palette.css('color'),
				fill: color,
				strokeWidth: lineWidth
			});
			canvas.add(shapeState.shape);
			break;
        case 'shape-arrow':
			canvas.remove(shapeState.shape);
			shapeState.shape = new fabric.Polyline(getArrowKeypoints(startPoint, endPoint), {
				left: Math.min(endPoint.x, startPoint.x),
				top: Math.min(endPoint.y, startPoint.y),
				stroke: palette.css('color'),
				strokeWidth: lineWidth,
                fill: '',
                strokeLineJoin: 'round'
			});
			canvas.add(shapeState.shape);
			break;
		default:
			break;
	}
	shapeState.shape.setCoords();
	canvas.renderAll();
}

function finishShape(shapeState) {
	if(!shapeState.started)
		return;
	if (shapeState.shape.width === 0 || shapeState.shape.height === 0) {
		//// console.log('useless shape');
		canvas.remove(shapeState.shape);
	}
	shapeState.shape.selectable = false;
	shapeState.startPoint = null;
	shapeState.endPoint = null;
	shapeState.started = false;
	shapeState.shape = null;
}

function fillShape(target){
	if(!target)
		return;
    if(fillableType.indexOf(target.type) === -1)
        return;
	const color = $('#shape-fill-color').css('background-color');
	target.set('fill',color);
	canvas.renderAll();
}

let prevTarget = null;
function showFillTarget(target){
	if(prevTarget)
		prevTarget.setShadow('');
	if(!target)
		return;
	if(fillableType.indexOf(target.type) === -1)
	    return;
	target.setShadow('1px 1px 5px rgba(0,0,0,0.6)');
	prevTarget = target;
}

function selectImage() {
	let input = document.createElement('input');
	input.type = 'file';
	input.accept = "image/*";
	input.setAttribute('onchange', 'loadImage(this)');
	input.style.display = 'none';
	document.body.appendChild(input);
	input.click();
}

function loadImage(dom) {
	status.text('导入图片中. . . . . .');
	docLoading();
	const maxLen = canvas.height - 80;
	const elem = document.createElement('img');
	let url = '';
	let reader = new FileReader();
	reader.onload = function (e) {
		url = e.target.result;
		elem.src = url;
		//缩放
		let rate = 1;
		const width = elem.width;
		const height = elem.height;
		if (width >= height) {
			if (width > maxLen) {
				rate = maxLen / width;
			}
		} else {
			if (height > maxLen) {
				rate = maxLen / height;
			}
		}
		elem.width = width * rate;
		elem.height = height * rate;
		const tempCanvas = document.createElement('canvas');
		tempCanvas.width = elem.width;
		tempCanvas.height = elem.height;
		tempCanvas.getContext('2d').drawImage(elem, 0, 0, elem.width, elem.height);
		elem.src = tempCanvas.toDataURL('image/webp', 0.8);
		let img = new fabric.Image(elem, {
			left: (canvas.width - elem.width) / 2,
			top: (canvas.height - elem.height) / 2
		});
		img.setCoords();
		canvas.add(img);
		canvas.setActiveObject(img);
		status.text('');
		DocManager.currentDoc.getPage(parseInt(currentPageNumber.text())).save(getCanvasJson());
		docLoaded();
	};
	reader.readAsDataURL(dom.files[0]);
	document.body.removeChild(dom);
}

function eraseTarget(point, target) {
	canvas.setCursor('pointer');
	if (eraserState.started) {
		const e = effect;
		e.set({
			left: point.x - e.radius,
			top: point.y - e.radius
		});
		if (target) {
			canvas.remove(target);
		}
		canvas.renderAll();
		return;
	}

	//仅悬浮鼠标
	if (target) {
		if (eraserState.target)
			eraserState.target.opacity = 1;
		eraserState.target = target;
		eraserState.target.opacity = '0.5';
	} else {
		if (eraserState.target)
			eraserState.target.opacity = 1;
	}
	canvas.renderAll();
}

function handleText(point, target) {
	//点击的是文字对象
	if (target && target.type === 'i-text') {
		//点击了其他文字对象
		if (target !== textState.target) {
			textState.isEditing = false;
			textState.target = null;
		}
		//点击了正在编辑的文字不做操作
		return;
	}

	//点击了非文字对象的区域

	//编辑状态则退出
	if (textState.isEditing) {
		textState.isEditing = false;
		textState.target = null;
		return;
	}

	//非编辑状态新建文字
	const size = textSizeMap.px[textSizeMap.word.indexOf($('#text-size-value').text())];
	let text = new fabric.IText('', {
		left: point.x,
		top: point.y,
		fontSize: parseInt(size),
		fontFamily: 'Microsoft YaHei UI',
		fill: palette.css('color')
	});
	text.on('editing:entered', function () {
		textState.target = this;
		textState.isEditing = true;
	});
	text.on('editing:exited', function () {
		if (this.text.trim() === '') {
			canvas.remove(this);
		}
	});
	canvas.add(text);
	canvas.setActiveObject(text);
	text.enterEditing();
}

function setTextCursor(target) {
	if (!(target && target.type === 'i-text')) {
		canvas.setCursor('text');
	}
}

function starPolygonPoints(R, r) {
	let points = [];
	for (let i = 0; i < 5; i++) {
		let x = Math.cos((18 + 72 * i) / 180 * Math.PI) * R;
		let y = - Math.sin((18 + 72 * i) / 180 * Math.PI) * R;
		points.push({
			x: x,
			y: y
		});

		x = Math.cos((54 + 72 * i) / 180 * Math.PI) * r;
		y = - Math.sin((54 + 72 * i) / 180 * Math.PI) * r;
		points.push({
			x: x,
			y: y
		});
	}
	return (points);
}

function getArrowKeypoints(startPoint, endPoint){
    const startX = startPoint.x;
    const startY = startPoint.y;
    const endX = endPoint.x;
    const endY = endPoint.y;
    const arrowRadius = 12;   //箭头尺寸大小
    let points = [startPoint, endPoint];
    //根据关系直线起至坐标获得线的夹角
    const tmpx = endX - startX;
    const tmpy = startY - endY;
    const angle = Math.atan2(tmpy, tmpx) * (180 / Math.PI);

    const centerX = endX - arrowRadius * Math.cos(angle * (Math.PI / 180));
    const centerY = endY + arrowRadius * Math.sin(angle * (Math.PI / 180));
    const leftX = centerX + arrowRadius * Math.cos((angle + 120) * (Math.PI / 180));
    const leftY = centerY - arrowRadius * Math.sin((angle + 120) * (Math.PI / 180));
    const rightX = centerX + arrowRadius * Math.cos((angle + 240) * (Math.PI / 180));
    const rightY = centerY - arrowRadius * Math.sin((angle + 240) * (Math.PI / 180));
    points.push({
        x: leftX,
        y: leftY
    });
    points.push(endPoint);

    points.push({
        x: rightX,
        y: rightY
    });
    points.push(endPoint);
    return points;
}

function strokeTarget(point, target){
    //url(icon/brush.ico),
	canvas.setCursor('pointer');
	if (brushState.started) {
		const e = effect;
		e.set({
			left: point.x - e.radius,
			top: point.y - e.radius,
			fill: brushState.color
		});
		if (target) {
			if(target.type === 'i-text')
				target.set('fill', brushState.color);
			else
				target.set('stroke', brushState.color);
		}
	}
	canvas.renderAll();
}
